import chalk from 'chalk';
import path from 'path';
import glob from 'glob';
import yargs from 'yargs/yargs';
import { Plugin } from './Plugin';
import { ConsoleBuilder } from '../routers/ConsoleBuilder';
import { ConsoleController } from '../routers/ConsoleController';
import { getVersion } from '../utils/getVersion';

export class PluginHelp extends Plugin<Plugin.Console> {
  protected builders: ConsoleBuilder[] = [];

  constructor() {
    super();
    this.use((ctx, next) => {
      const { command } = ctx;

      if (command === '') {
        if (ctx.argv.some((argv) => argv === '--version' || argv === '-v')) {
          console.log(getVersion());
        } else {
          this.showAllHelp(ctx.app.getPaths());
        }

        ctx.commandMatched = true;
        return;
      }

      if (ctx.argv.some((argv) => argv === '--help' || argv === '-h')) {
        for (let i = 0; i < this.builders.length; ++i) {
          const builder = this.builders[i];
          if (builder.match(command)) {
            const options = builder.pluginOptions.getData();

            if (
              !options['help'] && ctx.argv.includes('--help') ||
              !options['h'] && ctx.argv.includes('-h')
            ) {
              this.showCustomHelp(builder);
              ctx.commandMatched = true;
              return;
            }
          }
        }
      }

      return next();
    });
  }

  public appendBuilders(builders: ConsoleBuilder[]): this {
    this.builders.push(...builders);
    return this;
  }

  protected showAllHelp(commandsPath: string[]) {
    const cli = yargs([])
      .scriptName('fomex')
      .usage('fomex [command] [options] [--help|-h]')
      .describe('version', 'Show fomex version number')
      .alias('v', 'version')
      .alias('h', 'help');

    commandsPath.forEach((item) => {
      glob.sync(path.resolve(item, '**/!(*.d).{ts,js}')).forEach((matchPath) => {
        const modules = require(matchPath);
        Object.values(modules).forEach((moduleItem) => {
          if (moduleItem && moduleItem instanceof ConsoleController) {
            moduleItem.getBuilders().forEach((builder) => {
              const command = builder.toJSON();

              if (command.showInHelp) {
                command.commands[0] = chalk.yellow(command.commands[0]);
                cli.command(command.commands, command.description);
              }
            });
          }
        });
      });
    });

    cli.showHelp('log');
  }

  protected showCustomHelp(builder: ConsoleBuilder) {
    const data = builder.toJSON();
    const cli = yargs([])
        .scriptName('fomex')
        .usage(`fomex ${data.commands[0]} [options]${data.description  ? '\n\n' + chalk.bold(data.description) : ''}`)
        .version(false)
        .help(false);

    data.options.forEach((option) => {
      cli.option(option.name, {
        alias: option.alias,
        description: option.description,
        default: option.defaultValue === '' ? undefined : option.defaultValue,
      });
    });

    // Show help option last
    cli
      .alias('help', 'h')
      .describe('help', 'Show help for command ' + data.commands[0])

    cli.showHelp('log');
  }
}
